注释

/*多行注释,使用 xxx部分就是要注释的内容
快捷键 shift+ alt + a */

变量
//什么是变量?
//变量可以理解为就是一个容器,然后这个容器一次只能装一个东西
//如果变量装了第二个内容,那么第一个内容就会移除

//变量是计算机内存中存储数据的标识符，根据变量名称可以获取到内存中存储的数据

//var 是一个关键字 用于声明变量 声明变量的时候就要使用var关键字  let??
// ES6 新增了let命令，用来声明局部变量。它的用法类似于var，但是所声明的变量，只在let命令所在的代码块内有效，而且有暂时性死区的约束。
//let变量不能重复声明
//let没有变量提升与暂时性死区
//let 配合for循环的独特应用

//注意:
//1.一个变量只能放一个值
//2.给变量重新赋值的时候,前面的值会被覆盖
//3.变量命名严格区分大小写
//在js中 等号是用于赋值操作的 就是将等号右边的值赋值给等号左边的变量

// - 规则： 必须遵守的，不遵守就是错
// 1. 一个变量名称可以由 数字、字母、英文下划线（_）、美元符号（$） 组成
// 3. 不能由数字开头，中文命名合法 符合语法规范 但是不推荐
// 2. 严格区分大小写
// 4. 不能是 保留字 或者 关键字
// 不需要立马全部记住, 需要的时候查文档就可以了,编辑器会进行提示
// https://www.runoob.com/js/js-reserved.html

// 5. 不要出现空格
// var ms g ='123'
//     - 规范： 建议遵守的（开发者默认），不遵守不会报错
// 1. 变量名尽量有意义（语义化）
// var salary = 17000;
// 2. 遵循驼峰命名规则，由多个单词组成的时候，从第二个单词开始首字母大写 
//js中-后的单词用首字母大写代替

BEM
//　BEM代表块（Block），元素（Element），修饰符（Modifier）。无论是什么网站页面，都可以拆解成这三部分。
// BEM的命名规矩很容易记：block-name__element-name–modifier-name，也就是模块名 + 元素名 + 修饰器名。

数据类型

// 基本数据类型  放在栈中

// Number 数值类型 1234567890
// String 字符串 带引号的都是字符串 
// Boolean 布尔 只有两个值true 或者 false
// undefined 未定义 一般情况下 undefined不需要赋
//变量声明不赋值就是undefined 或者 对象的属性没有赋值也是undefined
// null 空  当一个变量赋值为null的时候 会释放内存

//引用数据类型  堆(heap)内存中的数据

// Object（在JS中除了基本数据类型以外的都是对象，数据是对象，函数是对象，正则表达式是对象）

判断数据类型

//1.typeof 是一个操作符，其右侧跟一个一元表达式，并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示，包括以下 7 种：number、boolean、symbol、string、object、undefined、function 等。
//对于基本类型，除 null 以外，均可以返回正确的结果。
//对于 null ，返回 object 类型。

//null需特殊处理
// toString() 是 Object 的原型方法，调用该方法，默认返回当前对象的 [[Class]] 。这是一个内部属性，其格式为 [object Xxx] ，其中 Xxx 就是对象的类型。

// 对于 Object 对象，直接调用 toString()  就能返回 [object Object] 。而对于其他对象，则需要通过 call / apply 来调用才能返回正确的类型信息。
//所有的typeof返回值为‘object’的对象都包含一个内部属性[[Class]],我们将它可以看做内部的分类，而非传统面向对象意义的分类。这个属性无法直接访问，一般通过
// Object.prototype.toString   来查看。

//2.instanceof 是用来判断 A 是否为 B 的实例，表达式为：A instanceof B，如果 A 是 B 的实例，则返回 true,否则返回 false。 在这里需要特别注意的是：instanceof 检测的是原型，我们用一段伪代码来模拟其内部执行过程

//A 的 __proto__ 指向 B 的 prototype 时，就认为 A 就是 B 的实例

//instanceof 能够判断出 [ ] 是Array的实例，但它认为 [ ] 也是Object的实例，为什么呢？

// [ ]、Array、Object 三者之间的关系：
// 从 instanceof 能够判断出 [ ].__proto__  指向 Array.prototype，而 Array.prototype.__proto__ 又指向了Object.prototype，最终 Object.prototype.__proto__ 指向了null，标志着原型链的结束。

//instanceof 只能用来判断两个对象是否属于实例关系， 而不能判断一个对象实例具体属于哪种类型。

//Array.isArray() 本质上检测的是对象的 [[Class]] 值，[[Class]] 是对象的一个内部属性，里面包含了对象的类型信息，其格式为 [object Xxx] ，Xxx 就是对应的具体类型 。对于数组而言，[[Class]] 的值就是 [object Array] 。

//constructor  toString
Object.prototype.toString.call('');  // [object String]
Object.prototype.toString.call(1);   // [object Number]
Object.prototype.toString.call(true);// [object Boolean]
Object.prototype.toString.call(Symbol());//[object Symbol]
Object.prototype.toString.call(undefined);// [object Undefined]
Object.prototype.toString.call(null);// [object Null]
Object.prototype.toString.call(newFunction());// [object Function]
Object.prototype.toString.call(newDate());// [object Date]
Object.prototype.toString.call([]);// [object Array]
Object.prototype.toString.call(newRegExp());// [object RegExp]
Object.prototype.toString.call(newError());// [object Error]
Object.prototype.toString.call(document);// [object HTMLDocument]
Object.prototype.toString.call(window);//[object global] window 是全局对象 global 的引用

//判断一个变量是不是一个数字
//isNaN   is not a number

//js设计缺陷
//true其实是数字1
//false其实是数字0
//null 其实也是0 
// console.log(isNaN(nul));//false
// console.log(isNaN(flag));//false
//NaN不是一个数字 但是确是一个数值类型
// console.log(typeof NaN);//number类型
// console.log(isNaN(NaN));//true       
//如果数值相加,+号左右两边,任意一边不是数字(字符串类型除外)得到的值是NaN
//0 null unefined '' NaN 得到的布尔值结果是false 其余的都是true
// == 一等是赋值 两等是比较 两等比较的是值

// !xxx 为空  ！！xxx 不为空

//前置++是先自加再使用，而后置++是先使用再自加！

逻辑判断

//抛出异常
//throw new Error('type error: age must be a number')

//switch case会'穿透' 导致会一直往下执行
//阻止穿透 使用break
//    switch (fruit) {
//     case '香蕉':
//         alert('18块')
//         break;
//     default: //不满足上述条件 进入到default
//         alert('不卖')
// }

//三元表达式
//?号左边如果返回的布尔值是true 那么就执行:号左边的语句 如果?左边返回的布尔值是false 那么就执行:右边的语句// var msg = 1 + 1 === 3 ? '正确' : '错误'

循环

//循环结构的内容
// 1. 初始化
// 2. 条件判断
// 3. 要执行的代码
// 4. 自身改变

// 在for循环的循环体中可以使用下面两个关键字来对循环进行操作
//continue continue 遇到continue的时候,那么continue下面的代码将不会执行,循环会直接跳过当前循环,进行到下一次循环
//break break后面的代码不会执行 直接跳出整个循环 break只影响自身代码所在的上下文(context)










